home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 October: Mac OS SDK / Dev.CD Oct 96 SDK / Dev.CD Oct 96 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc Source Code / Memory / MemMgrM.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-22  |  10.6 KB  |  422 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        MemMgrM.cpp
  3.  
  4.     Contains:    Mac-specific implementations of MemMgr calls
  5.  
  6.     Owned by:    Jens Alfke
  7.  
  8.     Copyright:    © 1994 - 1995 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.     
  12.         <10>    10/24/95    jpa        1293441: Added slush-fund. Allocate
  13.                                     temp-mem handles out of app heap if
  14.                                     absolutely necessary.
  15.          <9>     10/4/95    jpa        MMCopyHandle allocates in current heap's
  16.                                     area. [1289074]
  17.          <8>      5/5/95    TJ        jpa: ApplicZone --> ApplicationZone.
  18.          <7>      5/4/95    jpa        Added free-space fns, and maintain a
  19.                                     certain minimum free space in handle
  20.                                     allocation ops [1235657]
  21.          <6>     1/25/95    jpa        Removed HandToHand workaround now that
  22.                                     we're on Dagon a2. [1209733]
  23.          <5>     1/12/95    jpa        Took out five-dollar-sign mark and added
  24.                                     Radar bug 1209733. [1210981]
  25.          <4>     12/5/94    jpa        Nuked errant pragma lib_export's. [1195676]
  26.          <3>    10/12/94    JA        Added 68k workaround for HandToHand; no
  27.                                     effect on PPC build.
  28.          <2>     9/29/94    RA        1189812: Mods for 68K build.
  29.          <1>     9/14/94    jpa        first checked in
  30.  
  31.     To Do:
  32.     In Progress:
  33.         
  34. */
  35.  
  36.  
  37. #ifndef _MEMMGR_
  38. #include "MemMgr.h"
  39. #endif
  40.  
  41. #ifndef _MEMMGRPV_
  42. #include "MemMgrPv.h"
  43. #endif
  44.  
  45. #ifndef _MEMDEBG_
  46. #include "MemDebg.h"
  47. #endif
  48.  
  49. #ifndef __MEMORY__
  50. #include <Memory.h>        // Mac memory manager
  51. #endif
  52.  
  53. #ifndef __ERRORS__
  54. #include <Errors.h>
  55. #endif
  56.  
  57.  
  58. const size_t kMaxHandleBlockSize = 0x7FFFFFFF;
  59.  
  60. #if MM_DEBUG
  61. const size_t kTempMemFudge = 1000*1024;
  62. #else
  63. const size_t kTempMemFudge =  100*1024;
  64. #endif
  65.  
  66.  
  67. static void MMSystemFreeSpace( Zone *zone, size_t *total, size_t *contig );
  68.  
  69.  
  70. static MMBoolean
  71. FreeSpaceLow( MMHandle h )
  72. {
  73.     if( !h )
  74.         return kMMFalse;
  75.     Zone *zone = ::HandleZone((Handle)h);
  76.     if( MemError() )
  77.         return kMMTrue;
  78.     size_t free,contig;
  79.     MMSystemFreeSpace(zone,&free,&contig);
  80.     return (free < kPlatformMinFreeSpace || contig < kPlatformMinContigSpace);
  81. }
  82.  
  83.  
  84. //========================================================================================
  85. // OPERATIONS ON RELOCATABLE BLOCKS (HANDLES)
  86. //========================================================================================
  87.  
  88.  
  89. //----------------------------------------------------------------------------------------
  90. // MMAllocateHandle
  91. //----------------------------------------------------------------------------------------
  92.  
  93. MMHandle MMAllocateHandle(size_t howBig)
  94. {
  95.     return MMAllocateHandleIn(howBig,gDefaultHeap->GetLocation());
  96. }
  97.  
  98. //----------------------------------------------------------------------------------------
  99. // MMAllocateHandleIn
  100. //----------------------------------------------------------------------------------------
  101.  
  102. MMHandle MMAllocateHandleIn(size_t size, MMHeapLocation loc)
  103. {
  104. #if MMDebug
  105.     if( size>kMaxHandleBlockSize ) {
  106.         MM_WARN("Bogus size 0x%08lx for MMAllocateHandle",size);
  107.         return kMMNULL;
  108.     }
  109. #endif
  110.  
  111.     Handle handle;
  112.     OSErr err;
  113.     
  114.     switch( loc ) {
  115.         case kMMSysMemory:
  116.             handle = ::NewHandleSys(size);
  117.             err = MemError();
  118.             break;
  119.         case kMMAppMemory:
  120.             SetZone(ApplicationZone());
  121.             handle = ::NewHandle(size);
  122.             err = MemError();
  123.             break;
  124.         case kMMTempMemory:
  125.             handle = ::TempNewHandle(size, &err);
  126.             break;
  127.         default:
  128.             MM_WARN("MMAllocateHandleIn: Bogus memory source!");
  129.             return 0;
  130.     }
  131.     
  132.     if( err!=noErr && err!=memFullErr )
  133.         MM_WARN("MMAllocateHandle got err %d",err);
  134.     
  135.     if( FreeSpaceLow(handle) ) {
  136.         DisposeHandle(handle);
  137.         handle = kMMNULL;
  138.     }
  139.  
  140.     if( handle == kMMNULL && loc==kMMTempMemory ) {
  141.         // Allow temp-mem handle to be allocated out of app heap if there's room.
  142.         // It's easy for temp-mem to become totally wedged (just launch an app whose
  143.         // "preferred size" is greater than the amount available), which would
  144.         // otherwise totally prevent allocation of handles.
  145.         handle = (Handle) MMAllocateHandleIn(size,kMMAppMemory);
  146.     }
  147.     
  148. #if MMDebug
  149.     if( gValidate>0 && handle )
  150.         Zap(*(Handle)handle, size, 0xBBBBBBBB);
  151. #endif
  152.  
  153.     return (MMHandle) handle;
  154. }
  155.  
  156. //----------------------------------------------------------------------------------------
  157. // MMFreeHandle
  158. //----------------------------------------------------------------------------------------
  159.  
  160. void MMFreeHandle(MMHandle handle)
  161. {
  162.     if( handle != kMMNULL ) {
  163. #if MMDebug
  164.         if( gValidate>0 ) {
  165.             if( !MMValidateHandle(handle) )
  166.                 return;
  167.             Zap(*(Handle)handle, GetHandleSize((Handle)handle), 0xDD);
  168.         }
  169.         
  170.         if( HGetState((Handle)handle) & 0x20 ) {
  171.             MM_WARN("MMFreeHandle: Tried to dispose rsrc %p",handle);
  172.             return;
  173.         }
  174. #endif
  175.         
  176.         DisposeHandle((Handle)handle);
  177.         
  178. #if MMDebug
  179.         OSErr err = MemError();
  180.         if( err!=noErr )
  181.             MM_WARN("MMFreeHandle: DisposeHandle returned err %d",err);
  182. #endif
  183.     }
  184. }
  185.  
  186. //----------------------------------------------------------------------------------------
  187. // MMCopyHandle
  188. //----------------------------------------------------------------------------------------
  189.  
  190. MMHandle MMCopyHandle( MMHandle handle )
  191. {
  192.     if( handle == kMMNULL ) {
  193.         MM_WARN("MMCopyHandle(NULL)!");
  194.         return kMMNULL;
  195.     }
  196.  
  197. #if MMDebug
  198.     if( gValidate>0 )
  199.         if( !MMValidateHandle(handle) )
  200.             return kMMNULL;
  201.     if( (HGetState((Handle)handle)&0x20) && !(HGetState((Handle)handle)&0x80) )
  202.         MM_WARN("Copying purgeable handle %p",handle);
  203. #endif
  204.  
  205.     size_t size = GetHandleSize((Handle) handle);
  206.     if( MemError() ) {
  207.         MM_WARN("MMCopyHandle got err %d",MemError());
  208.         return kMMNULL;
  209.     }
  210.     
  211.     MMHandle copy = MMAllocateHandle(size);
  212.     if( copy ) {
  213.         PlatformCopyMemory(*(Handle)handle,*(Handle)copy,size);
  214.         if( FreeSpaceLow(copy) ) {
  215.             MMFreeHandle(copy);
  216.             copy = kMMNULL;
  217.         }
  218.     }
  219.     return copy;
  220. }
  221.  
  222. //----------------------------------------------------------------------------------------
  223. // MMGetHandleSize(MMHandle handle)
  224. //----------------------------------------------------------------------------------------
  225.  
  226. size_t MMGetHandleSize(MMHandle handle)
  227. {
  228.     size_t    blkSize;
  229.     
  230. #if MMDebug
  231.     if( gValidate>0 )
  232.         if( !MMValidateHandle(handle) )
  233.             return 0;
  234. #endif
  235.         
  236.     blkSize = GetHandleSize((Handle) handle);
  237.     if( MemError() ) {
  238.         MM_WARN("MMGetHandleSize got err %d",MemError());
  239.         blkSize = 0;
  240.     }
  241.     return blkSize;
  242. }
  243.  
  244. //----------------------------------------------------------------------------------------
  245. // MMSetHandleSize(MMHandle handle, size_t blkSize)
  246. //----------------------------------------------------------------------------------------
  247.  
  248. MMBoolean MMSetHandleSize(MMHandle handle, size_t blkSize)
  249. {
  250.     size_t oldSize = ::GetHandleSize((Handle)handle);
  251.     
  252.     if( blkSize == oldSize )
  253.         return kMMTrue;
  254.     
  255. #if MMDebug
  256.     if( blkSize>kMaxHandleBlockSize ) {
  257.         MM_WARN("Bogus blkSize %08lx for MMSetHandleSize",blkSize);
  258.         return kMMFalse;
  259.     }
  260.     if( gValidate>0 ) {
  261.         if( !MMValidateHandle(handle) )
  262.             return kMMFalse;
  263.         // If block will shrink, zap area that will be lost:
  264.         if( blkSize < oldSize )
  265.             memset(OFFSET(*(Handle)handle,blkSize), 0xDD, oldSize-blkSize);
  266.     }
  267. #endif
  268.     
  269.     SetHandleSize((Handle) handle, blkSize);
  270.     OSErr err = MemError();
  271.     if( err ) {
  272.         if( err!=memFullErr )
  273.             MM_WARN("MMSetHandleSize got err %d",err);
  274.         return kMMFalse;
  275.     }
  276.     
  277.     if( blkSize>oldSize && FreeSpaceLow(handle) ) {
  278.         ::SetHandleSize((Handle)handle,oldSize);        // Back out the change
  279.         return kMMFalse;
  280.     }
  281.  
  282. #if MMDebug
  283.     // If block grew, zap new space at end:
  284.     if( gValidate>0 )
  285.         if( blkSize > oldSize )
  286.             memset(OFFSET(*(Handle)handle,oldSize),0xBB,(size_t)(blkSize-oldSize));    // Fill new space with BB
  287. #endif
  288.  
  289.     return kMMTrue;
  290. }
  291.  
  292. //----------------------------------------------------------------------------------------
  293. // MMLockHandle(MMHandle handle)
  294. //----------------------------------------------------------------------------------------
  295.  
  296. void* MMLockHandle(MMHandle handle)
  297. {
  298. #if MMDebug
  299.     if( gValidate>0 )
  300.         if( !MMValidateHandle(handle) )
  301.             return kODNULL;
  302. #endif
  303.         
  304.     HLock((Handle) handle);
  305.     OSErr err = MemError();
  306.     if( err ) {
  307.         MM_WARN("MMLockHandle got err %d",err);
  308.         return kMMNULL;
  309.     }
  310.     
  311.     return *(Handle) handle;
  312. }
  313.  
  314. //----------------------------------------------------------------------------------------
  315. // MMUnlockPtr(void* ptr)
  316. //----------------------------------------------------------------------------------------
  317.  
  318. void MMUnlockPtr(void* ptr)
  319. {
  320.     if( ptr==kMMNULL ) {
  321.         MM_WARN("MMUnlockPtr(NULL)!");
  322.     } else {
  323.         MMHandle handle = (MMHandle) RecoverHandle((Ptr) ptr);
  324.         if( MemError() )
  325.             MM_WARN("MMUnlockPtr(%p) got err %d",ptr,MemError());
  326.         else if (handle != kMMNULL) {
  327. #if MMDebug
  328.             if( HGetState((Handle)handle) & 0x80) )
  329.                 MM_WARN("MMUnlockPtr(%p): Hdl %p already unlocked",ptr,h);
  330. #endif
  331.             HUnlock((Handle) handle);
  332.         }
  333.     }
  334. }
  335.  
  336. //----------------------------------------------------------------------------------------
  337. // MMUnlockHandle(MMHandle handle)
  338. //----------------------------------------------------------------------------------------
  339.  
  340. void MMUnlockHandle(MMHandle handle)
  341. {
  342. #if MMDebug
  343.     if( gValidate>0 )
  344.         if( !MMValidateHandle(handle) )
  345.             THROW(kMMErrMemoryProblem);
  346. #endif
  347.         
  348.     HUnlock((Handle) handle);
  349.     if( MemError() )
  350.         MM_WARN("MMUnlockHandle(%p) got err %d",handle,MemError());
  351. }
  352.  
  353.  
  354. //----------------------------------------------------------------------------------------
  355. // MMSystemFreeSpace
  356. //----------------------------------------------------------------------------------------
  357.  
  358. void MMSystemFreeSpace( MMHeapLocation loc, size_t *total, size_t *contig )
  359. {
  360.     size_t tempTotal, tempContig;
  361.     if( !total ) total = &tempTotal;
  362.     if( !contig) contig= &tempContig;
  363.     
  364.     Zone *zone = kMMNULL;
  365.     
  366.     switch( loc ) {
  367.         case kMMSysMemory:
  368.             zone = SystemZone();
  369.             break;
  370.             
  371.         case kMMAppMemory:
  372.             zone = ApplicationZone();
  373.             break;
  374.             
  375.         case kMMTempMemory: {
  376.             // Find the temp zone by allocating a handle in it and then getting its zone.
  377.             // Cannot cache this value because the Process Mgr zone's header can move!
  378.             OSErr err;
  379.             Handle handle = ::TempNewHandle(1, &err);
  380.             if( handle ) {
  381.                 zone = ::HandleZone(handle);
  382.                 ::DisposeHandle(handle);
  383.             }
  384.         }
  385.     }
  386.     MMSystemFreeSpace(zone,total,contig);
  387. }
  388.  
  389.  
  390. static void MMSystemFreeSpace( Zone *zone, size_t *total, size_t *contig )
  391. {
  392.     if( zone ) {
  393.         Zone *curZone = GetZone();
  394.         SetZone(zone);
  395.         
  396.         *total = FreeMem();
  397.         *contig = MaxBlock();
  398.         size_t purgeTotal, purgeContig; 
  399.         PurgeSpace((long*)&purgeTotal,(long*)&purgeContig);
  400.         if( purgeTotal > *total )
  401.             *total = purgeTotal;
  402.         if( purgeContig > *contig )
  403.             *contig = purgeContig;
  404.  
  405.         // Return an unnaturally low number for Temp Mem availability, to make it easier
  406.         // to debug and to reflect the fact that running out of temp mem is incredibly
  407.         // dangerous to the whole system.
  408.         if( kTempMemFudge > 0 && zone!=ApplicationZone() && zone!=SystemZone() ) {
  409.             // (It would be nice to have a better way to detect the temp mem zone.)
  410.             if( *total >= kTempMemFudge )
  411.                 *total -= kTempMemFudge;
  412.             else
  413.                 *total = 0;
  414.             if( *contig > *total )
  415.                 *contig = *total;
  416.         }
  417.         
  418.         SetZone(curZone);
  419.     } else
  420.         *total = *contig = 0;
  421. }
  422.